package widget

import (
	"archive/zip"
	"fmt"
	"os"
	"strings"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/data/binding"
	"fyne.io/fyne/v2/dialog"
	"fyne.io/fyne/v2/storage"
	"fyne.io/fyne/v2/theme"
	"fyne.io/fyne/v2/widget"
	"github.com/gogf/gf/v2/container/garray"
	"github.com/gogf/gf/v2/os/gfile"
	"github.com/gogf/gf/v2/util/gconv"
)

// NewOpenFile
// bdFilePath := binding.NewString()
// filters:=[]string{".jpg",".jpeg",".png"}
// filters:=[]string{".zip",".rar",".tar"}
// openFile := NewOpenFile(bdFilePath,filters w)
func NewOpenFile(data binding.String, lbl string, filters []string,
	w fyne.Window) *fyne.Container {
	return container.NewBorder(nil, nil, widget.NewLabel(lbl),
		widget.NewButtonWithIcon("", theme.FileIcon(), func() {
			d := dialog.NewFileOpen(func(uc fyne.URIReadCloser, e error) {
				if uc == nil {
					return
				}
				data.Set(uc.URI().String()[7:])
			}, w)
			luri, _ := storage.ListerForURI(storage.NewFileURI("."))

			d.SetFilter(storage.NewExtensionFileFilter(filters))
			d.SetLocation(luri)
			d.Show()
		}),
		widget.NewEntryWithData(data))
}

// NewOpenFolder 打开目录
// NewOpenFolder bdFolderPath := binding.NewString()
// openFolder := NewOpenFolder(outData, w)
func NewOpenFolder(data binding.String, lbl string, w fyne.Window) *fyne.Container {
	return container.NewBorder(nil, nil, widget.NewLabel(lbl),
		widget.NewButtonWithIcon("",
			theme.FolderOpenIcon(), func() {
				d := dialog.NewFolderOpen(func(lu fyne.ListableURI, e error) {
					if lu == nil {
						return
					}
					data.Set(lu.Path())
				}, w)
				luri, _ := storage.ListerForURI(storage.NewFileURI("."))
				d.SetLocation(luri)
				d.Show()
			}), widget.NewEntryWithData(data))
}

// NewOpenFolder2 打开目录并执行传入的操作 fn
func NewOpenFolder2(data binding.String, fn func(), w fyne.Window) *fyne.Container {
	return container.NewBorder(nil, nil, widget.NewButtonWithIcon("",
		theme.FolderOpenIcon(), func() {
			d := dialog.NewFolderOpen(func(lu fyne.ListableURI, e error) {
				if lu == nil {
					return
				}
				data.Set(lu.Path())
				fn()
			}, w)
			luri, _ := storage.ListerForURI(storage.NewFileURI("."))
			d.SetLocation(luri)
			d.Show()
		}), widget.NewButton("Ok", func() {
		d, _ := data.Get()
		if d != "" && fn != nil {
			fn()
		}
	}), widget.NewEntryWithData(data))
}

// List display data list that can be converted to string
// 用列表控件显示能转换成字符串的数据列表
func List(items ...interface{}) *widget.List {
	return widget.NewList(func() int {
		return len(items)
	},
		func() fyne.CanvasObject {
			return widget.NewLabel("list")
		},
		func(lii widget.ListItemID, co fyne.CanvasObject) {
			lbl := co.(*widget.Label)
			lbl.SetText(gconv.String(items[lii]))
		})
}

// List display data list that can be converted to string
// 用列表控件显示实现fmt.Stringer接口的数据列表
func List2(items ...fmt.Stringer) *widget.List {
	if len(items) == 0 {
		return &widget.List{}
	}
	return widget.NewList(func() int {
		return len(items)
	},
		func() fyne.CanvasObject {
			return widget.NewLabel("list")
		},
		func(lii widget.ListItemID, co fyne.CanvasObject) {
			co.(*widget.Label).SetText(items[lii].String())
		})
}


// Ziptree 构建zip压缩包文件树
// root zip文件路径
func Ziptree(root string) *widget.Tree {
	if !gfile.Exists(root) {
		return &widget.Tree{}
	}
	data := make(map[string][]string)
	reader, _ := zip.OpenReader(root)
	defer reader.Close()
	gs := garray.NewSortedStrArray()
	sepStr := string(os.PathSeparator)
	for _, file := range reader.File {
		path := strings.TrimRight(file.Name, sepStr)
		dn := strings.Split(path, sepStr)
		// println(path, len(dn))
		switch len(dn) {
		case 1:
			gs.Add(path)
			data[""] = gs.Unique().Sort().Slice()
		case 2:
			data[dn[0]] = append(data[dn[0]], path)
		case 3:
			key := strings.Join(dn[:2], sepStr)
			data[key] = append(data[key], path)
		case 4:
			key := strings.Join(dn[:3], sepStr)
			data[key] = append(data[key], path)
		}
	}
	tree := widget.NewTreeWithStrings(data)
	// tree.UpdateNode = func(uid widget.TreeNodeID, branch bool,
	// 	node fyne.CanvasObject) {
	// 	lbl := node.(*widget.Label)
	// 	dn := strings.Split(uid, sepStr)
	// 	switch len(dn) {
	// 	case 1:
	// 		lbl.SetText(uid)
	// 	case 2:
	// 		lbl.SetText(dn[1])
	// 		case 3:
	// 			lbl.SetText(dn[2])
	// 		case 4:
	// 			lbl.SetText(dn[3])
	// 	}
	// }
	// tree.Refresh()
	return tree
}

// Filetree 根据路径root构建树
func Filetree(tree *widget.Tree, root string) *widget.Tree {
	if !gfile.Exists(root) {
		return tree
	}
	tree.Root = root
	tree.ChildUIDs = func(uid widget.TreeNodeID) (c []widget.TreeNodeID) {
		if uid == "" {
			c, _ = gfile.ScanDir(root, "*")
		} else {
			c, _ = gfile.ScanDir(uid, "*")
		}
		c = gfile.SortFiles(c)

		return
	}
	tree.IsBranch = func(uid widget.TreeNodeID) (ok bool) {
		return gfile.IsDir(uid)
	}
	tree.CreateNode = func(branch bool) (o fyne.CanvasObject) {
		return container.NewHBox(&widget.FileIcon{}, widget.NewLabel("tree"))
	}
	tree.UpdateNode = func(uid widget.TreeNodeID, branch bool,
		node fyne.CanvasObject) {
		box := node.(*fyne.Container)
		icon := box.Objects[0].(*widget.FileIcon)
		icon.URI = storage.NewFileURI(uid)
		icon.Refresh()
		lbl := box.Objects[1].(*widget.Label)
		lbl.SetText(gfile.Name(uid))
	}
	tree.Refresh()

	return tree
}
